package com.spukmk3me.impl.libgdx;

import com.spukmk3me.util.Util;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.spukmk3me.GameProcessor;
import com.spukmk3me.Platform;
import com.spukmk3me.io.FileSystem;
import com.spukmk3me.io.userinput.ButtonInput;
import com.spukmk3me.io.userinput.PointerInput;
import com.spukmk3me.resource.ResourceManager;
import com.spukmk3me.scene.Scene;
import com.spukmk3me.scenepack.pack0.DefaultScene;
import com.spukmk3me.sound.SoundPlayer;
import com.spukmk3me.video.VideoAPI;

public class LibgdxEntryPoint extends Platform implements ApplicationListener
{
    public LibgdxEntryPoint( LibgdxFileHandlerResolver resolver )
    {
        PLATFORM = this;
        
        if ( resolver == null )
            RESOLVER = new LibgdxDefaultFileHandlerResolver();
        else
            RESOLVER = resolver;

        m_running = true;
    }
    
    @Override
    public final FileSystem getFileSystem()
    {
        return m_fSys;
    }

    @Override
    public final ResourceManager getResourceManager()
    {
        return m_rMan;
    }

    @Override
    public final Scene getScene()
    {
        return m_scene;
    }

    @Override
    public final VideoAPI getVideoAPI()
    {
        return m_vAPI;
    }
    
    @Override
    public final SoundPlayer getSoundPlayer()
    {
        return m_sndP;
    }
    
    @Override
    public PointerInput getPointerInput()
    {
        return m_pInput;
    }
    
    @Override
    public ButtonInput getButtonInput()
    {
        return m_bInput;
    }

    @Override
    public final void setGameProcessor( GameProcessor processor )
    {
        m_gameProcessor = processor;
    }
    
    @Override
    public synchronized final void create()
    {
        Util.initialiseRandomSeed( System.currentTimeMillis() );
        m_fSys = new LibgdxFileSystem();
        m_rMan = new ResourceManager();
        m_rMan.addResourceLoader( new LibgdxResourceCreator() );
        m_vAPI = new LibgdxVideoAPI();
        m_sndP = new LibgdxSoundPlayer();
        m_vAPI.init();
        m_scene = new DefaultScene();
        m_scene.setVideoAPI( m_vAPI );
        m_pInput = new LibgdxPointerInput();
        m_bInput = new LibgdxButtonInput();
        
        InputMultiplexer iMultiplexer = new InputMultiplexer( m_pInput, m_bInput );
        
        Gdx.input.setInputProcessor( iMultiplexer );
        Gdx.input.setCatchBackKey( true );
    }

    @Override
    public final void resize( int width, int height )
    {
        m_vAPI.resize( width, height );
    }

    @Override
    public final void render()
    {
        if ( m_running )
        {
            long deltaTimeMS = (long)(Gdx.graphics.getDeltaTime() * 1000);
            deltaTimeMS = Math.min( deltaTimeMS, m_maxDeltaMSPF );
            
            int deltaTimeI = Util.convertMilisecToFP( (int)deltaTimeMS );
            
            //checkReloadTextures();
            
            m_pInput.process();
            m_bInput.process( deltaTimeI );
            
            if ( m_gameProcessor != null )
                m_running = !m_gameProcessor.process( deltaTimeI );
            
            m_vAPI.startRendering( true, 0, deltaTimeMS );
            m_scene.render( deltaTimeI );
            m_vAPI.finishRendering();
            
            if ( !m_running )
                Gdx.app.exit();
        }
    }

    @Override
    public synchronized final void pause()
    {
        m_gameProcessor.pause();
        m_vAPI.clearTextures();
        m_vAPI.markGLCreateNewContext();
    }

    @Override
    public synchronized final void resume()
    {
        m_gameProcessor.resume();
    }

    @Override
    public final void dispose()
    {
        m_gameProcessor.quit();
        m_scene.dropChildren( m_scene.getRoot() );
        m_sndP.clearSounds();
        m_rMan.clearAllUnusedResource();
        m_vAPI.cleanup();
    }
    
    @Override
    public final void setMaximumDeltaMSPerFrame( long deltaMS )
    {
        m_maxDeltaMSPF = deltaMS;
    }
    
    @Override
    public long getMaximumDeltaMSPerFrame()
    {
        return m_maxDeltaMSPF;
    }
    
    public static LibgdxFileHandlerResolver RESOLVER;
    
    private LibgdxVideoAPI      m_vAPI;
    private LibgdxSoundPlayer   m_sndP;
    private LibgdxFileSystem    m_fSys;
    private ResourceManager     m_rMan;
    private Scene               m_scene;
    private LibgdxPointerInput  m_pInput;
    private LibgdxButtonInput   m_bInput;
    private GameProcessor       m_gameProcessor;
    
    private long                m_maxDeltaMSPF;
    private boolean             m_running;
}
